home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i091: Sun RPC Source (rpc2), Part03/11
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- Submitted by: cca!SUN.COM!marks (Mark Stein)
- Mod.sources: Volume 6, Issue 91
- Archive-name: rpc2/Part03
-
- [ All I did was verity that the shar files unpacked correctly. -r$ ]
-
- Sun RPC source (part 3 of 11). This software package contains code
- and documentation for Revision 3.0 of the Sun Remote Procedure Call
- library. In addition, a beta version of the XDR/RPC protocol compiler
- is included. Comments about this latest release may be mailed to
- sun!rpc or rpc@sun.com.
-
- Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- unrestricted use provided that this legend is included on all tape
- media and as a part of the software program in whole or part. Users
- may copy or modify Sun RPC without charge, but are not authorized to
- license or distribute it to anyone else except as part of a product or
- program developed by the user.
-
- - - - - - - - - - C U T - H E R E - - - - - - - - - - - - - - - - - -
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # rpc/doc/xdr.spec.p1
- # This archive created: Mon Jul 14 16:55:03 1986
- export PATH; PATH=/bin:/usr/bin:$PATH
- for d in rpc rpc/doc rpc/rpclib rpc/tools rpc/toys rpc/rpclib/profiled rpc/rpcgen rpc/rpcgen/test
- do
- if test ! -d $d
- then
- echo "shar: Making directory $d"
- mkdir $d
- chmod 755 $d
- fi
- done
- echo shar: "extracting 'rpc/doc/xdr.spec.p1'" '(49809 characters)'
- if test -f 'rpc/doc/xdr.spec.p1'
- then
- echo shar: "will not over-write existing file 'rpc/doc/xdr.spec.p1'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpc/doc/xdr.spec.p1'
- X.\" @(#)c3.xdr.spec 1.1 86/02/25 SMI; for 3.0 FCS
- X.PL RIGHT
- X.EQ
- Xdelim $$
- X.EN
- X.TL
- XExternal Data Representation
- X.br
- XProtocol Specification
- X.bp
- X.NH
- XIntroduction
- X.LP
- XThis manual describes library routines that allow a C programmer to
- Xdescribe arbitrary data structures in a machine-independent fashion.
- XThe eXternal Data Representation (XDR) standard
- Xis the backbone of Sun's Remote Procedure Call package,
- Xin the sense that data for remote procedure calls
- Xis transmitted using the standard.
- XXDR library routines should be used to transmit data
- Xthat is accessed (read or written) by more than one type of machine.
- X.LP
- XThis manual contains a description of XDR library routines,
- Xa guide to accessing currently available XDR streams,
- Xinformation on defining new streams and data types,
- Xand a formal definition of the XDR standard.
- XXDR was designed to work across different languages,
- Xoperating systems, and machine architectures.
- XMost users (particularly RPC users)
- Xonly need the information in sections 2 and 3 of this document.
- XProgrammers wishing to implement RPC and XDR on new machines
- Xwill need the information in sections 4 through 6.
- XAdvanced topics, not necessary for all implementations,
- Xare covered in section 7.
- X.LP
- XOn Sun systems,
- XC programs that want to use XDR routines
- Xmust include the file
- X.LW <rpc/rpc.h> ,
- Xwhich contains all the necessary interfaces to the XDR system.
- XSince the C library
- X.LW libc.a
- Xcontains all the XDR routines,
- Xcompile as normal.
- X.LS
- X% \f(LBcc\0\fIprogram\fP.c\fL
- X.Lf
- X.NH 2
- XJustification
- X.LP
- XConsider the following two programs,
- X.LW writer :
- X.LS
- X#include <stdio.h>
- X.sp.5
- Xmain() /* writer.c */
- X{
- X long i;
- X.sp.5
- X for (i = 0; i < 8; i++) {
- X if (fwrite((char *)&i, sizeof(i), 1, stdout) != 1) {
- X fprintf(stderr, "failed!\en");
- X exit(1);
- X }
- X }
- X}
- X.Lf
- Xand
- X.LW reader :
- X.LS
- X#include <stdio.h>
- X.sp.5
- Xmain() /* reader.c */
- X{
- X long i, j;
- X.sp.5
- X for (j = 0; j < 8; j++) {
- X if (fread((char *)&i, sizeof (i), 1, stdin) != 1) {
- X fprintf(stderr, "failed!\en");
- X exit(1);
- X }
- X printf("%ld ", i);
- X }
- X printf("\en");
- X}
- X.Lf
- XThe two programs appear to be portable, because
- X(a) they pass
- X.LW lint
- Xchecking, and
- X(b) they exhibit the same behavior when executed
- Xon two different hardware architectures, a Sun and a VAX.
- X.LP
- XPiping the output of the
- X.LW writer
- Xprogram to the
- X.LW reader
- Xprogram gives identical results on a Sun or a VAX.\(dd
- X.FS \(dd
- XVAX is a trademark of Digital Equipment Corporation.
- X.FE
- X.LS
- Xsun% writer | reader
- X0 1 2 3 4 5 6 7
- Xsun%
- X.Lf
- X.LS
- Xvax% writer | reader
- X0 1 2 3 4 5 6 7
- Xvax%
- X.Lf
- XWith the advent of local area networks and Berkeley's 4.2 BSD
- X.UX
- Xcame the concept of ``network pipes'' \(em
- Xa process produces data on one machine,
- Xand a second process consumes data on another machine.
- XA network pipe can be constructed with
- X.LW writer
- Xand
- X.LW reader .
- XHere are the results if the first produces data on a Sun,
- Xand the second consumes data on a VAX.
- X.LS
- Xsun% writer | rsh vax reader
- X0 16777216 33554432 50331648 67108864 83886080 100663296
- X117440512
- Xsun%
- X.Lf
- XIdentical results can be obtained by executing
- X.LW writer
- Xon the VAX and
- X.LW reader
- Xon the Sun.
- XThese results occur because the byte ordering
- Xof long integers differs between the VAX and the Sun,
- Xeven though word size is the same.
- XNote that $16777216$ is $2 sup 24$ \(em
- Xwhen four bytes are reversed, the 1 winds up in the 24th bit.
- X.LP
- XWhenever data is shared by two or more machine types,
- Xthere is a need for portable data.
- XPrograms can be made data-portable by replacing the
- X.LW read()
- Xand
- X.LW write()
- Xcalls with calls to an XDR library routine
- X.LW xdr_long() ,
- Xa filter that knows the standard representation
- Xof a long integer in its external form.
- XHere are the revised versions of
- X.LW writer :
- X.LS
- X#include <stdio.h>
- X#include <rpc/rpc.h> /* xdr is a sub-library of rpc */
- X.sp.5
- Xmain() /* writer.c */
- X{
- X XDR xdrs;
- X long i;
- X.sp.5
- X xdrstdio_create(&xdrs, stdout, XDR_ENCODE);
- X for (i = 0; i < 8; i++) {
- X if (!xdr_long(&xdrs, &i)) {
- X fprintf(stderr, "failed!\en");
- X exit(1);
- X }
- X }
- X}
- X.Lf
- Xand
- X.LW reader :
- X.LS
- X#include <stdio.h>
- X#include <rpc/rpc.h> /* xdr is a sub-library of rpc */
- X.sp.5
- Xmain() /* reader.c */
- X{
- X XDR xdrs;
- X long i, j;
- X.sp.5
- X xdrstdio_create(&xdrs, stdin, XDR_DECODE);
- X for (j = 0; j < 8; j++) {
- X if (!xdr_long(&xdrs, &i)) {
- X fprintf(stderr, "failed!\en");
- X exit(1);
- X }
- X printf("%ld ", i);
- X }
- X printf("\en");
- X}
- X.Lf
- XThe new programs were executed on a Sun,
- Xon a VAX, and from a Sun to a VAX;
- Xthe results are shown below.
- X.LS
- Xsun% writer | reader
- X0 1 2 3 4 5 6 7
- Xsun%
- X.Lf
- X.LS
- Xvax% writer | reader
- X0 1 2 3 4 5 6 7
- Xvax%
- X.Lf
- X.LS
- Xsun% writer | rsh vax reader
- X0 1 2 3 4 5 6 7
- Xsun%
- X.Lf
- XDealing with integers is just the tip of the portable-data iceberg.
- XArbitrary data structures present portability problems,
- Xparticularly with respect to alignment and pointers.
- XAlignment on word boundaries may cause the
- Xsize of a structure to vary from machine to machine.
- XPointers are convenient to use,
- Xbut have no meaning outside the machine where they are defined.
- X.NH 2
- XThe XDR Library
- X.LP
- XThe XDR library solves data portability problems.
- XIt allows you to write and read arbitrary C constructs
- Xin a consistent, specified, well-documented manner.
- XThus, it makes sense to use the library even when the data
- Xis not shared among machines on a network.
- X.LP
- XThe XDR library has filter routines for
- Xstrings (null-terminated arrays of bytes),
- Xstructures, unions, and arrays, to name a few.
- XUsing more primitive routines,
- Xyou can write your own specific XDR routines
- Xto describe arbitrary data structures,
- Xincluding elements of arrays, arms of unions,
- Xor objects pointed at from other structures.
- XThe structures themselves may contain arrays of arbitrary elements,
- Xor pointers to other structures.
- X.LP
- XLet's examine the two programs more closely.
- XThere is a family of XDR stream creation routines
- Xin which each member treats the stream of bits differently.
- XIn our example, data is manipulated using standard I/O routines,
- Xso we use
- X.LW xdrstdio_create() .
- XThe parameters to XDR stream creation routines
- Xvary according to their function.
- XIn our example,
- X.LW xdrstdio_create()
- Xtakes a pointer to an XDR structure that it initializes,
- Xa pointer to a
- X.LW FILE
- Xthat the input or output is performed on, and the operation.
- XThe operation may be
- X.LW XDR_ENCODE
- Xfor serializing in the
- X.LW writer
- Xprogram, or
- X.LW XDR_DECODE
- Xfor deserializing in the
- X.LW reader
- Xprogram.
- X.LP
- XNote: RPC clients never need to create XDR streams;
- Xthe RPC system itself creates these streams,
- Xwhich are then passed to the clients.
- X.LP
- XThe
- X.LW xdr_long()
- Xprimitive is characteristic of most XDR library
- Xprimitives and all client XDR routines.
- XFirst, the routine returns
- X.LW FALSE
- X(0) if it fails, and
- X.LW TRUE
- X(1) if it succeeds.
- XSecond, for each data type,
- X.LW xxx ,
- Xthere is an associated XDR routine of the form:
- X.LS
- Xxdr_xxx(xdrs, fp)
- X XDR *xdrs;
- X xxx *fp;
- X{
- X}
- X.Lf
- XIn our case,
- X.LW xxx
- Xis long, and the corresponding XDR routine is
- Xa primitive,
- X.LW xdr_long .
- XThe client could also define an arbitrary structure
- X.LW xxx
- Xin which case the client would also supply the routine
- X.LW xdr_xxx ,
- Xdescribing each field by calling XDR routines
- Xof the appropriate type.
- XIn all cases the first parameter,
- X.LW xdrs
- Xcan be treated as an opaque handle,
- Xand passed to the primitive routines.
- X.LP
- XXDR routines are direction independent;
- Xthat is, the same routines are called to serialize or deserialize data.
- XThis feature is critical to software engineering of portable data.
- XThe idea is to call the same routine for either operation \(em
- Xthis almost guarantees that serialized data can also be deserialized.
- XOne routine is used by both producer and consumer of networked data.
- XThis is implemented by always passing the address
- Xof an object rather than the object itself \(em
- Xonly in the case of deserialization is the object modified.
- XThis feature is not shown in our trivial example,
- Xbut its value becomes obvious when nontrivial data structures
- Xare passed among machines.
- XIf needed, you can obtain the direction of the XDR operation.
- XSee section 3.7 for details.
- X.LP
- XLet's look at a slightly more complicated example.
- XAssume that a person's gross assets and liabilities
- Xare to be exchanged among processes.
- XAlso assume that these values are important enough
- Xto warrant their own data type:
- X.LS
- Xstruct gnumbers {
- X long g_assets;
- X long g_liabilities;
- X};
- X.Lf
- XThe corresponding XDR routine describing this structure would be:
- X.LS
- Xbool_t /* TRUE is success, FALSE is failure */
- Xxdr_gnumbers(xdrs, gp)
- X XDR *xdrs;
- X struct gnumbers *gp;
- X{
- X if (xdr_long(xdrs, &gp->g_assets) &&
- X xdr_long(xdrs, &gp->g_liabilities))
- X return(TRUE);
- X return(FALSE);
- X}
- X.Lf
- XNote that the parameter
- X.LW xdrs
- Xis never inspected or modified;
- Xit is only passed on to the subcomponent routines.
- XIt is imperative to inspect the return value of each XDR routine call,
- Xand to give up immediately and return
- X.LW FALSE
- Xif the subroutine fails.
- X.LP
- XThis example also shows that the type
- X.LW bool_t
- Xis declared as an integer whose only values are
- X.LW TRUE
- X(1) and
- X.LW FALSE
- X(0). This document uses the following definitions:
- X.LS
- X#define bool_t int
- X#define TRUE 1
- X#define FALSE 0
- X.sp.5
- X#define enum_t int /* enum_t used for generic enums */
- X.Lf
- X.LP
- XKeeping these conventions in mind,
- X.LW xdr_gnumbers()
- Xcan be rewritten as follows:
- X.LS
- Xxdr_gnumbers(xdrs, gp)
- X XDR *xdrs;
- X struct gnumbers *gp;
- X{
- X return(xdr_long(xdrs, &gp->g_assets) &&
- X xdr_long(xdrs, &gp->g_liabilities));
- X}
- X.Lf
- XThis document uses both coding styles.
- X.bp
- X.NH
- XXDR Library Primitives
- X.LP
- XThis section gives a synopsis of each XDR primitive.
- XIt starts with basic data types and moves on to constructed data types.
- XFinally, XDR utilities are discussed.
- XThe interface to these primitives
- Xand utilities is defined in the include file
- X.LW <rpc/xdr.h> ,
- Xautomatically included by
- X.LW <rpc/rpc.h> .
- X.NH 2
- XNumber Filters
- X.LP
- XThe XDR library provides primitives to translate between numbers
- Xand their corresponding external representations.
- XPrimitives cover the set of numbers in:
- X.EQ
- X[signed, unsigned] * [short, int, long]
- X.EN
- XSpecifically, the six primitives are:
- X.LS
- Xbool_t xdr_int(xdrs, ip)
- X XDR *xdrs;
- X int *ip;
- X.sp.5
- Xbool_t xdr_u_int(xdrs, up)
- X XDR *xdrs;
- X unsigned *up;
- X.sp.5
- Xbool_t xdr_long(xdrs, lip)
- X XDR *xdrs;
- X long *lip;
- X.sp.5
- Xbool_t xdr_u_long(xdrs, lup)
- X XDR *xdrs;
- X u_long *lup;
- X.sp.5
- Xbool_t xdr_short(xdrs, sip)
- X XDR *xdrs;
- X short *sip;
- X.sp.5
- Xbool_t xdr_u_short(xdrs, sup)
- X XDR *xdrs;
- X u_short *sup;
- X.Lf
- XThe first parameter,
- X.LW xdrs ,
- Xis an XDR stream handle.
- XThe second parameter is the address of the number
- Xthat provides data to the stream or receives data from it.
- XAll routines return
- X.LW TRUE
- Xif they complete successfully, and
- X.LW FALSE
- Xotherwise.
- X.NH 2
- XFloating Point Filters
- X.LP
- XThe XDR library also provides primitive routines
- Xfor C's floating point types:
- X.LS
- Xbool_t xdr_float(xdrs, fp)
- X XDR *xdrs;
- X float *fp;
- X.sp.5
- Xbool_t xdr_double(xdrs, dp)
- X XDR *xdrs;
- X double *dp;
- X.Lf
- XThe first parameter,
- X.LW xdrs
- Xis an XDR stream handle.
- XThe second parameter is the address
- Xof the floating point number that provides data to the stream
- Xor receives data from it.
- XAll routines return
- X.LW TRUE
- Xif they complete successfully, and
- X.LW FALSE
- Xotherwise.
- X.LP
- XNote: Since the numbers are represented in IEEE floating point,
- Xroutines may fail when decoding a valid IEEE representation
- Xinto a machine-specific representation, or vice-versa.
- X.NH 2
- XEnumeration Filters
- X.LP
- XThe XDR library provides a primitive for generic enumerations.
- XThe primitive assumes that a C
- X.LW enum
- Xhas the same representation inside the machine as a C integer.
- XThe boolean type is an important instance of the
- X.LW enum .
- XThe external representation of a boolean is always one
- X.LW TRUE ) (
- Xor zero
- X.LW FALSE ). (
- X.LS
- X#define bool_t int
- X#define FALSE 0
- X#define TRUE 1
- X.sp.5
- X#define enum_t int
- X.sp.5
- Xbool_t xdr_enum(xdrs, ep)
- X XDR *xdrs;
- X enum_t *ep;
- X.sp.5
- Xbool_t xdr_bool(xdrs, bp)
- X XDR *xdrs;
- X bool_t *bp;
- X.Lf
- XThe second parameters
- X.LW ep
- Xand
- X.LW bp
- Xare addresses of the associated type
- Xthat provides data to, or receives data from, the stream
- X.LW xdrs .
- XThe routines return
- X.LW TRUE
- Xif they complete successfully, and
- X.LW FALSE
- Xotherwise.
- X.NH 2
- XNo Data
- X.LP
- XOccasionally, an XDR routine must be supplied to the RPC system,
- Xeven when no data is passed or required.
- XThe library provides such a routine:
- X.LS
- Xbool_t xdr_void(); /* always returns TRUE */
- X.Lf
- X.NH 2
- XConstructed Data Type Filters
- X.LP
- XConstructed or compound data type primitives
- Xrequire more parameters and perform more complicated functions
- Xthen the primitives discussed above.
- XThis section includes primitives for
- Xstrings, arrays, unions, and pointers to structures.
- X.LP
- XConstructed data type primitives may use memory management.
- XIn many cases, memory is allocated when deserializing data with
- X.LW XDR_DECODE .
- XTherefore, the XDR package must provide means to deallocate memory.
- XThis is done by an XDR operation,
- X.LW XDR_FREE .
- XTo review, the three XDR directional operations are
- X.LW XDR_ENCODE ,
- X.LW XDR_DECODE ,
- Xand
- X.LW XDR_FREE .
- X.NH 3
- XStrings
- X.LP
- XIn C, a string is defined as a sequence of bytes
- Xterminated by a null byte,
- Xwhich is not considered when calculating string length.
- XHowever, when a string is passed or manipulated,
- Xa pointer to it is employed.
- XTherefore, the XDR library defines a string to be a
- X.LW "char *" ,
- Xand not a sequence of characters.
- XThe external representation of a string is drastically different
- Xfrom its internal representation.
- XExternally, strings are represented as
- Xsequences of ASCII characters,
- Xwhile internally, they are represented with character pointers.
- XConversion between the two representations
- Xis accomplished with the routine
- X.LW xdr_string() :
- X.LS
- Xbool_t xdr_string(xdrs, sp, maxlength)
- X XDR *xdrs;
- X char **sp;
- X u_int maxlength;
- X.Lf
- XThe first parameter
- X.LW xdrs
- Xis the XDR stream handle.
- XThe second parameter
- X.LW sp
- Xis a pointer to a string (type
- X.LW "char **" ).
- XThe third parameter
- X.LW maxlength
- Xspecifies the maximum number of bytes allowed during encoding or decoding;
- Xits value is usually specified by a protocol.
- XFor example, a protocol specification may say
- Xthat a file name may be no longer than 255 characters.
- XThe routine returns
- X.LW FALSE
- Xif the number of characters exceeds
- X.LW maxlength ,
- Xand
- X.LW TRUE
- Xif it doesn't.
- X.LP
- XThe behavior of
- X.LW xdr_string()
- Xis similar to the behavior of other routines
- Xdiscussed in this section. The direction
- X.LW XDR_ENCODE
- Xis easiest to understand. The parameter
- X.LW sp
- Xpoints to a string of a certain length;
- Xif it does not exceed
- X.LW maxlength ,
- Xthe bytes are serialized.
- X.LP
- XThe effect of deserializing a string is subtle.
- XFirst the length of the incoming string is determined;
- Xit must not exceed
- X.LW maxlength .
- XNext
- X.LW sp
- Xis dereferenced; if the the value is
- X.LW NULL ,
- Xthen a string of the appropriate length is allocated and
- X.LW *sp
- Xis set to this string.
- XIf the original value of
- X.LW *sp
- Xis non-null, then the XDR package assumes
- Xthat a target area has been allocated,
- Xwhich can hold strings no longer than
- X.LW maxlength .
- XIn either case, the string is decoded into the target area.
- XThe routine then appends a null character to the string.
- X.LP
- XIn the
- X.LW XDR_FREE
- Xoperation, the string is obtained by dereferencing
- X.LW sp .
- XIf the string is not
- X.LW NULL ,
- Xit is freed and
- X.LW *sp
- Xis set to
- X.LW NULL .
- XIn this operation,
- X.LW xdr_string
- Xignores the
- X.LW maxlength
- Xparameter.
- X.NH 3
- XByte Arrays
- X.LP
- XOften variable-length arrays of bytes are preferable to strings.
- XByte arrays differ from strings in the following three ways:
- X1) the length of the array (the byte count) is explicitly
- Xlocated in an unsigned integer,
- X2) the byte sequence is not terminated by a null character, and
- X3) the external representation of the bytes is the same as their
- Xinternal representation.
- XThe primitive
- X.LW xdr_bytes()
- Xconverts between the internal and external
- Xrepresentations of byte arrays:
- X.LS
- Xbool_t xdr_bytes(xdrs, bpp, lp, maxlength)
- X XDR *xdrs;
- X char **bpp;
- X u_int *lp;
- X u_int maxlength;
- X.Lf
- XThe usage of the first, second and fourth parameters
- Xare identical to the first, second and third parameters of
- X.LW xdr_string() ,
- Xrespectively.
- XThe length of the byte area is obtained by dereferencing
- X.LW lp
- Xwhen serializing;
- X.LW *lp
- Xis set to the byte length when deserializing.
- X.NH 3
- XArrays
- X.LP
- XThe XDR library package provides a primitive
- Xfor handling arrays of arbitrary elements.
- XThe
- X.LW xdr_bytes()
- Xroutine treats a subset of generic arrays,
- Xin which the size of array elements is known to be 1,
- Xand the external description of each element is built-in.
- XThe generic array primitive,
- X.LW xdr_array()
- Xrequires parameters identical to those of
- X.LW xdr_bytes()
- Xplus two more:
- Xthe size of array elements,
- Xand an XDR routine to handle each of the elements.
- XThis routine is called to encode or decode
- Xeach element of the array.
- X.LS
- Xbool_t
- Xxdr_array(xdrs, ap, lp, maxlength, elementsiz, xdr_element)
- X XDR *xdrs;
- X char **ap;
- X u_int *lp;
- X u_int maxlength;
- X u_int elementsiz;
- X bool_t (*xdr_element)();
- X.Lf
- XThe parameter
- X.LW ap
- Xis the address of the pointer to the array.
- XIf
- X.LW *ap
- Xis
- X.LW NULL
- Xwhen the array is being deserialized,
- XXDR allocates an array of the appropriate size and sets
- X.LW *ap
- Xto that array.
- XThe element count of the array is obtained from
- X.LW *lp
- Xwhen the array is serialized;
- X.LW *lp
- Xis set to the array length when the array is deserialized.
- XThe parameter
- X.LW maxlength
- Xis the maximum number of elements that the array is allowed to have;
- X.LW elementsiz
- Xis the byte size of each element of the array
- X(the C function
- X.LW sizeof()
- Xcan be used to obtain this value).
- XThe routine
- X.LW xdr_element
- Xis called to serialize, deserialize, or free
- Xeach element of the array.
- X.NH 4
- XExamples
- X.LP
- XBefore defining more constructed data types,
- Xit is appropriate to present three examples.
- X.LP
- X.I "Example A"
- X.LP
- XA user on a networked machine can be identified by
- X(a) the machine name, such as
- X.LW krypton :
- Xsee
- X.I gethostname (3);
- X(b) the user's UID: see
- X.I geteuid (2);
- Xand (c) the group numbers to which the user belongs: see
- X.I getgroups (2).
- XA structure with this information and its associated XDR routine
- Xcould be coded like this:
- X.LS
- Xstruct netuser {
- X char *nu_machinename;
- X int nu_uid;
- X u_int nu_glen;
- X int *nu_gids;
- X};
- X#define NLEN 255 /* machine names < 256 chars */
- X#define NGRPS 20 /* user can't be in > 20 groups */
- X.sp.5
- Xbool_t
- Xxdr_netuser(xdrs, nup)
- X XDR *xdrs;
- X struct netuser *nup;
- X{
- X return(xdr_string(xdrs, &nup->nu_machinename, NLEN) &&
- X xdr_int(xdrs, &nup->nu_uid) &&
- X xdr_array(xdrs, &nup->nu_gids, &nup->nu_glen, NGRPS,
- X sizeof (int), xdr_int));
- X}
- X.Lf
- X.LP
- X.I "Example B"
- X.LP
- XA party of network users could be implemented
- Xas an array of
- X.LW netuser
- Xstructure.
- XThe declaration and its associated XDR routines
- Xare as follows:
- X.LS
- Xstruct party {
- X u_int p_len;
- X struct netuser *p_nusers;
- X};
- X#define PLEN 500 /* max number of users in a party */
- X.sp.5
- Xbool_t
- Xxdr_party(xdrs, pp)
- X XDR *xdrs;
- X struct party *pp;
- X{
- X return(xdr_array(xdrs, &pp->p_nusers, &pp->p_len, PLEN,
- X sizeof (struct netuser), xdr_netuser));
- X}
- X.Lf
- X.LP
- X.I "Example C"
- X.LP
- XThe well-known parameters to
- X.LW main() ,
- X.LW argc
- Xand
- X.LW argv
- Xcan be combined into a structure.
- XAn array of these structures can make up a history of commands.
- XThe declarations and XDR routines might look like:
- X.LS no
- Xstruct cmd {
- X u_int c_argc;
- X char **c_argv;
- X};
- X#define ALEN 1000 /* args cannot be > 1000 chars */
- X#define NARGC 100 /* commands cannot have > 100 args */
- X.sp.5
- Xstruct history {
- X u_int h_len;
- X struct cmd *h_cmds;
- X};
- X#define NCMDS 75 /* history is no more than 75 commands */
- X.sp.5
- Xbool_t
- Xxdr_wrap_string(xdrs, sp)
- X XDR *xdrs;
- X char **sp;
- X{
- X return(xdr_string(xdrs, sp, ALEN));
- X}
- X.sp.5
- Xbool_t
- Xxdr_cmd(xdrs, cp)
- X XDR *xdrs;
- X struct cmd *cp;
- X{
- X return(xdr_array(xdrs, &cp->c_argv, &cp->c_argc, NARGC,
- X sizeof (char *), xdr_wrap_string));
- X}
- X.sp.5
- Xbool_t
- Xxdr_history(xdrs, hp)
- X XDR *xdrs;
- X struct history *hp;
- X{
- X return(xdr_array(xdrs, &hp->h_cmds, &hp->h_len, NCMDS,
- X sizeof (struct cmd), xdr_cmd));
- X}
- X.Lf
- XThe most confusing part of this example is that the routine
- X.LW xdr_wrap_string()
- Xis needed to package the
- X.LW xdr_string()
- Xroutine, because the implementation of
- X.LW xdr_array()
- Xonly passes two parameters to the array element description routine;
- X.LW xdr_wrap_string()
- Xsupplies the third parameter to
- X.LW xdr_string() .
- X.LP
- XBy now the recursive nature of the XDR library should be obvious.
- XLet's continue with more constructed data types.
- X.NH 3
- XOpaque Data
- X.LP
- XIn some protocols, handles are passed from a server to client.
- XThe client passes the handle back to the server at some later time.
- XHandles are never inspected by clients;
- Xthey are obtained and submitted.
- XThat is to say, handles are opaque.
- XThe primitive
- X.LW xdr_opaque()
- Xis used for describing fixed sized, opaque bytes.
- X.LS
- Xbool_t xdr_opaque(xdrs, p, len)
- X XDR *xdrs;
- X char *p;
- X u_int len;
- X.Lf
- XThe parameter
- X.LW p
- Xis the location of the bytes;
- X.LW len
- Xis the number of bytes in the opaque object.
- XBy definition, the actual data
- Xcontained in the opaque object are not machine portable.
- X.NH 3
- XFixed Sized Arrays
- X.LP
- XThe XDR library does not provide a primitive for fixed-length arrays
- X(the primitive
- X.LW xdr_array()
- Xis for varying-length arrays).
- XExample A could be rewritten to use fixed-sized arrays
- Xin the following fashion:
- X.LS no
- X#define NLEN 255 /* machine names must be < 256 chars */
- X#define NGRPS 20 /* user can't belong to > 20 groups */
- X.sp.5
- Xstruct netuser {
- X char *nu_machinename;
- X int nu_uid;
- X int nu_gids[NGRPS];
- X};
- X.sp.5
- Xbool_t
- Xxdr_netuser(xdrs, nup)
- X XDR *xdrs;
- X struct netuser *nup;
- X{
- X int i;
- X.sp.5
- X if (!xdr_string(xdrs, &nup->nu_machinename, NLEN))
- X return(FALSE);
- X if (!xdr_int(xdrs, &nup->nu_uid))
- X return(FALSE);
- X for (i = 0; i < NGRPS; i++) {
- X if (!xdr_int(xdrs, &nup->nu_gids[i]))
- X return(FALSE);
- X }
- X return(TRUE);
- X}
- X.Lf
- X.LP
- XExercise:
- XRewrite example A so that it uses varying-length arrays and so that the
- X.LW netuser
- Xstructure contains the actual
- X.LW nu_gids
- Xarray body as in the example above.
- X.NH 3
- XDiscriminated Unions
- X.LP
- XThe XDR library supports discriminated unions.
- XA discriminated union is a C union and an
- X.LW enum_t
- Xvalue that selects an ``arm'' of the union.
- X.LS
- Xstruct xdr_discrim {
- X enum_t value;
- X bool_t (*proc)();
- X};
- X.sp.5
- Xbool_t xdr_union(xdrs, dscmp, unp, arms, defaultarm)
- X XDR *xdrs;
- X enum_t *dscmp;
- X char *unp;
- X struct xdr_discrim *arms;
- X bool_t (*defaultarm)(); /* may equal NULL */
- X.Lf
- XFirst the routine translates the discriminant of the union located at
- X.LW *dscmp .
- XThe discriminant is always an
- X.LW enum_t .
- XNext the union located at
- X.LW *unp
- Xis translated.
- XThe parameter
- X.LW arms
- Xis a pointer to an array of
- X.LW xdr_discrim
- Xstructures.
- XEach structure contains an order pair of
- X.LW [value,proc] .
- XIf the union's discriminant is equal to the associated
- X.LW value ,
- Xthen the
- X.LW proc
- Xis called to translate the union.
- XThe end of the
- X.LW xdr_discrim
- Xstructure array is denoted by a routine of value
- X.LW NULL
- X(0). If the discriminant is not found in the
- X.LW arms
- Xarray, then the
- X.LW defaultarm
- Xprocedure is called if it is non-null;
- Xotherwise the routine returns
- X.LW FALSE .
- X.LP
- X.I "Example D"
- X.LP
- XSuppose the type of a union may be integer,
- Xcharacter pointer (a string), or a
- X.LW gnumbers
- Xstructure.
- XAlso, assume the union and its current type
- Xare declared in a structure.
- XThe declaration is:
- X.LS
- Xenum utype { INTEGER=1, STRING=2, GNUMBERS=3 };
- X.sp.5
- Xstruct u_tag {
- X enum utype utype; /* the union's discriminant */
- X union {
- X int ival;
- X char *pval;
- X struct gnumbers gn;
- X } uval;
- X};
- X.Lf
- XThe following constructs and XDR procedure (de)serialize
- Xthe discriminated union:
- X.LS
- Xstruct xdr_discrim u_tag_arms[4] = {
- X { INTEGER, xdr_int },
- X { GNUMBERS, xdr_gnumbers }
- X { STRING, xdr_wrap_string },
- X { __dontcare__, NULL }
- X /* always terminate arms with a NULL xdr_proc */
- X}
- X.sp.5
- Xbool_t
- Xxdr_u_tag(xdrs, utp)
- X XDR *xdrs;
- X struct u_tag *utp;
- X{
- X return(xdr_union(xdrs, &utp->utype, &utp->uval,
- X u_tag_arms, NULL));
- X}
- X.Lf
- XThe routine
- X.LW xdr_gnumbers()
- Xwas presented in Section 2;
- X.LW xdr_wrap_string()
- Xwas presented in example C.
- XThe default arm parameter to
- X.LW xdr_union()
- X(the last parameter) is
- X.LW NULL
- Xin this example. Therefore the value of the union's discriminant
- Xmay legally take on only values listed in the
- X.LW u_tag_arms
- Xarray. This example also demonstrates that
- Xthe elements of the arm's array do not need to be sorted.
- X.LP
- XIt is worth pointing out that the values of the discriminant
- Xmay be sparse, though in this example they are not.
- XIt is always good
- Xpractice to assign explicitly integer values to each element of the
- Xdiscriminant's type.
- XThis practice both documents the external
- Xrepresentation of the discriminant and guarantees that different
- XC compilers emit identical discriminant values.
- X.LP
- XExercise: Implement
- X.LW xdr_union()
- Xusing the other primitives in this section.
- X.NH 3
- XPointers
- X.LP
- XIn C it is often convenient to put pointers
- Xto another structure within a structure.
- XThe primitive
- X.LW xdr_reference()
- Xmakes it easy to serialize, deserialize, and free
- Xthese referenced structures.
- X.LS
- Xbool_t xdr_reference(xdrs, pp, size, proc)
- X XDR *xdrs;
- X char **pp;
- X u_int ssize;
- X bool_t (*proc)();
- X.Lf
- X.LP
- XParameter
- X.LW pp
- Xis the address of
- Xthe pointer to the structure;
- Xparameter
- X.LW ssize
- Xis the size in bytes of the structure
- X(use the C function
- X.LW sizeof()
- Xto obtain this value); and
- X.LW proc
- Xis the XDR routine that describes the structure.
- XWhen decoding data, storage is allocated if
- X.LW *pp
- Xis
- X.LW NULL .
- X.LP
- XThere is no need for a primitive
- X.LW xdr_struct()
- Xto describe structures within structures,
- Xbecause pointers are always sufficient.
- X.LP
- XExercise: Implement
- X.LW xdr_reference()
- Xusing
- X.LW xdr_array() .
- XWarning:
- X.LW xdr_reference()
- Xand
- X.LW xdr_array()
- Xare NOT interchangeable external representations of data.
- X.LP
- X.I "Example E"
- X.LP
- XSuppose there is a structure containing a person's name
- Xand a pointer to a
- X.LW gnumbers
- Xstructure containing the person's gross assets and liabilities.
- XThe construct is:
- X.LS
- Xstruct pgn {
- X char *name;
- X struct gnumbers *gnp;
- X};
- X.Lf
- XThe corresponding XDR routine for this structure is:
- X.LS
- Xbool_t
- Xxdr_pgn(xdrs, pp)
- X XDR *xdrs;
- X struct pgn *pp;
- X{
- X if (xdr_string(xdrs, &pp->name, NLEN) &&
- X xdr_reference(xdrs, &pp->gnp,
- X sizeof(struct gnumbers), xdr_gnumbers))
- X return(TRUE);
- X return(FALSE);
- X}
- X.Lf
- X.NH 4
- XPointer Semantics and XDR
- X.LP
- XIn many applications,
- XC programmers attach double meaning to the values of a pointer.
- XTypically the value
- X.LW NULL
- X(or zero) means data is not needed,
- Xyet some application-specific interpretation applies.
- XIn essence, the C programmer is encoding
- Xa discriminated union efficiently
- Xby overloading the interpretation of the value of a pointer.
- XFor instance, in example E a
- X.LW NULL
- Xpointer value for
- X.LW gnp
- Xcould indicate that
- Xthe person's assets and liabilities are unknown.
- XThat is, the pointer value encodes two things:
- Xwhether or not the data is known;
- Xand if it is known, where it is located in memory.
- XLinked lists are an extreme example of the use
- Xof application-specific pointer interpretation.
- X.LP
- XThe primitive
- X.LW xdr_reference()
- Xcannot and does not attach any special
- Xmeaning to a null-value pointer during serialization.
- XThat is, passing an address of a pointer whose value is
- X.LW NULL
- Xto
- X.LW xdr_reference()
- Xwhen serialing data will most likely cause a memory fault and, on
- X.UX ,
- Xa core dump for debugging.
- X.LP
- XIt is the explicit responsibility of the programmer
- Xto expand non-dereferenceable pointers into their specific semantics.
- XThis usually involves describing data with a two-armed discriminated union.
- XOne arm is used when the pointer is valid;
- Xthe other is used when the pointer is invalid
- X.LW NULL ). (
- XSection 7 has an example (linked lists encoding) that deals
- Xwith invalid pointer interpretation.
- X.LP
- XExercise:
- XAfter reading Section 7, return here and extend example E so that
- Xit can correctly deal with null pointer values.
- X.LP
- XExercise:
- XUsing the
- X.LW xdr_union() ,
- X.LW xdr_reference()
- Xand
- X.LW xdr_void()
- Xprimitives, implement a generic pointer handling primitive
- Xthat implicitly deals with
- X.LW NULL
- Xpointers. The XDR library does not provide such a primitive
- Xbecause it does not want to give the illusion
- Xthat pointers have meaning in the external world.
- X.NH 2
- XNon-filter Primitives
- X.LP
- XXDR streams can be manipulated with
- Xthe primitives discussed in this section.
- X.LS
- Xu_int xdr_getpos(xdrs)
- X XDR *xdrs;
- X.sp.5
- Xbool_t xdr_setpos(xdrs, pos)
- X XDR *xdrs;
- X u_int pos;
- X.sp.5
- Xxdr_destroy(xdrs)
- X XDR *xdrs;
- X.Lf
- XThe routine
- X.LW xdr_getpos()
- Xreturns an unsigned integer
- Xthat describes the current position in the data stream.
- XWarning: In some XDR streams, the returned value of
- X.LW xdr_getpos()
- Xis meaningless;
- Xthe routine returns a \-1 in this case
- X(though \-1 should be a legitimate value).
- X.LP
- XThe routine
- X.LW xdr_setpos()
- Xsets a stream position to
- X.LW pos .
- XWarning: In some XDR streams, setting a position is impossible;
- Xin such cases,
- X.LW xdr_setpos()
- Xwill return
- X.LW FALSE .
- XThis routine will also fail if the requested position is out-of-bounds.
- XThe definition of bounds varies from stream to stream.
- X.LP
- XThe
- X.LW xdr_destroy()
- Xprimitive destroys the XDR stream.
- XUsage of the stream
- Xafter calling this routine is undefined.
- X.NH 2
- XXDR Operation Directions
- X.LP
- XAt times you may wish to optimize XDR routines by taking
- Xadvantage of the direction of the operation \(em
- X.LW XDR_ENCODE ,
- X.LW XDR_DECODE ,
- Xor
- X.LW XDR_FREE .
- XThe value
- X.LW xdrs->x_op
- Xalways contains the
- Xdirection of the XDR operation.
- XProgrammers are not encouraged to take advantage of this information.
- XTherefore, no example is presented here.
- XHowever, an example in Section 7
- Xdemonstrates the usefulness of the
- X.LW xdrs->x_op
- Xfield.
- X.bp
- X.NH
- XXDR Stream Access
- X.LP
- XAn XDR stream is obtained by calling the appropriate creation routine.
- XThese creation routines take arguments that are tailored to the
- Xspecific properties of the stream.
- X.LP
- XStreams currently exist for (de)serialization of data to or from
- Xstandard I/O
- X.LW FILE
- Xstreams, TCP/IP connections and
- X.UX
- Xfiles, and memory.
- XSection 5 documents the XDR object and how to make
- Xnew XDR streams when they are required.
- X.NH 2
- XStandard I/O Streams
- X.LP
- XXDR streams can be interfaced to standard I/O using the
- X.LW xdrstdio_create()
- Xroutine as follows:
- X.LS
- X#include <stdio.h>
- X#include <rpc/rpc.h> /* xdr streams part of rpc */
- X.sp.5
- Xvoid
- Xxdrstdio_create(xdrs, fp, x_op)
- X XDR *xdrs;
- X FILE *fp;
- X enum xdr_op x_op;
- X.Lf
- XThe routine
- X.LW xdrstdio_create()
- Xinitializes an XDR stream pointed to by
- X.LW xdrs .
- XThe XDR stream interfaces to the standard I/O library.
- XParameter
- X.LW fp
- Xis an open file, and
- X.LW x_op
- Xis an XDR direction.
- X.NH 2
- XMemory Streams
- X.LP
- XMemory streams allow the streaming of data into or out of
- Xa specified area of memory:
- X.LS
- X#include <rpc/rpc.h>
- X.sp.5
- Xvoid
- Xxdrmem_create(xdrs, addr, len, x_op)
- X XDR *xdrs;
- X char *addr;
- X u_int len;
- X enum xdr_op x_op;
- X.Lf
- XThe routine
- X.LW xdrmem_create()
- Xinitializes an XDR stream in local memory.
- XThe memory is pointed to by parameter
- X.LW addr ;
- Xparameter
- X.LW len
- Xis the length in bytes of the memory.
- XThe parameters
- X.LW xdrs
- Xand
- X.LW x_op
- Xare identical to the corresponding parameters of
- X.LW xdrstdio_create() .
- XCurrently, the UDP/IP implementation of RPC uses
- X.LW xdrmem_create() .
- XComplete call or result messages are built in memory before calling the
- X.LW sendto()
- Xsystem routine.
- X.NH 2
- XRecord (TCP/IP) Streams
- X.LP
- XA record stream is an XDR stream built on top of
- Xa record marking standard that is built on top of the
- X.UX
- Xfile or 4.2 BSD connection interface.
- X.LS
- X#include <rpc/rpc.h> /* xdr streams part of rpc */
- X.sp.5
- Xxdrrec_create(xdrs,
- X sendsize, recvsize, iohandle, readproc, writeproc)
- X XDR *xdrs;
- X u_int sendsize, recvsize;
- X char *iohandle;
- X int (*readproc)(), (*writeproc)();
- X.Lf
- XThe routine
- X.LW xdrrec_create()
- Xprovides an XDR stream interface that allows for a bidirectional,
- Xarbitrarily long sequence of records.
- XThe contents of the records are meant to be data in XDR form.
- XThe stream's primary use is for interfacing RPC to TCP connections.
- XHowever, it can be used to stream data into or out of normal
- X.UX
- Xfiles.
- X.LP
- XThe parameter
- X.LW xdrs
- Xis similar to the corresponding parameter described above.
- XThe stream does its own data buffering similar to that of standard I/O.
- XThe parameters
- X.LW sendsize
- Xand
- X.LW recvsize
- Xdetermine the size in bytes of the output and input buffers, respectively;
- Xif their values are zero (0), then predetermined defaults are used.
- XWhen a buffer needs to be filled or flushed, the routine
- X.LW readproc
- Xor
- X.LW writeproc
- Xis called, respectively.
- XThe usage and behavior of these
- Xroutines are similar to the
- X.UX
- Xsystem calls
- X.LW read()
- Xand
- X.LW write() .
- XHowever,
- Xthe first parameter to each of these routines is the opaque parameter
- X.LW iohandle .
- XThe other two parameters
- X.LW buf "" (
- Xand
- X.LW nbytes )
- Xand the results
- X(byte count) are identical to the system routines.
- XIf
- X.LW xxx
- Xis
- X.LW readproc
- Xor
- X.LW writeproc ,
- Xthen it has the following form:
- X.LS
- X/*
- X * returns the actual number of bytes transferred.
- X * -1 is an error
- X */
- Xint
- Xxxx(iohandle, buf, len)
- X char *iohandle;
- X char *buf;
- X int nbytes;
- X.Lf
- XThe XDR stream provides means for delimiting records in the byte stream.
- XThe implementation details of delimiting records in a stream
- Xare discussed in appendix 1.
- XThe primitives that are specific to record streams are as follows:
- X.LS
- Xbool_t
- Xxdrrec_endofrecord(xdrs, flushnow)
- X XDR *xdrs;
- X bool_t flushnow;
- X.sp.5
- Xbool_t
- Xxdrrec_skiprecord(xdrs)
- X XDR *xdrs;
- X.sp.5
- Xbool_t
- Xxdrrec_eof(xdrs)
- X XDR *xdrs;
- X.Lf
- XThe routine
- X.LW xdrrec_endofrecord()
- Xcauses the current outgoing data to be marked as a record.
- XIf the parameter
- X.LW flushnow
- Xis
- X.LW TRUE ,
- Xthen the stream's
- X.LW writeproc()
- Xwill be called; otherwise,
- X.LW writeproc()
- Xwill be called when the output buffer has been filled.
- X.LP
- XThe routine
- X.LW xdrrec_skiprecord()
- Xcauses an input stream's position to be moved past
- Xthe current record boundary and onto the
- Xbeginning of the next record in the stream.
- X.LP
- XIf there is no more data in the stream's input buffer,
- Xthen the routine
- X.LW xdrrec_eof()
- Xreturns
- X.LW TRUE .
- XThat is not to say that there is no more data
- Xin the underlying file descriptor.
- X.bp
- X.NH
- XXDR Stream Implementation
- X.LP
- XThis section provides the abstract data types needed
- Xto implement new instances of XDR streams.
- X.NH 2
- XThe XDR Object
- X.LP
- XThe following structure defines the interface to an XDR stream:
- X.LS
- Xenum xdr_op { XDR_ENCODE=0, XDR_DECODE=1, XDR_FREE=2 };
- X.sp.5
- Xtypedef struct {
- X enum xdr_op x_op; /* operation; fast added param */
- X struct xdr_ops {
- X bool_t (*x_getlong)(); /* get long from stream */
- X bool_t (*x_putlong)(); /* put long to stream */
- X bool_t (*x_getbytes)(); /* get bytes from stream */
- X bool_t (*x_putbytes)(); /* put bytes to stream */
- X u_int (*x_getpostn)(); /* return stream offset */
- X bool_t (*x_setpostn)(); /* reposition offset */
- X caddr_t (*x_inline)(); /* ptr to buffered data */
- X VOID (*x_destroy)(); /* free private area */
- X } *x_ops;
- X caddr_t x_public; /* users' data */
- X caddr_t x_private; /* pointer to private data */
- X caddr_t x_base; /* private for position info */
- X int x_handy; /* extra private word */
- X} XDR;
- X.Lf
- XThe
- X.LW x_op
- Xfield is the current operation being performed on the stream.
- XThis field is important to the XDR primitives,
- Xbut should not affect a stream's implementation.
- XThat is, a stream's implementation should not depend
- Xon this value.
- XThe fields
- X.LW x_private ,
- X.LW x_base ,
- Xand
- X.LW x_handy
- Xare private to the particular
- Xstream's implementation.
- XThe field
- X.LW x_public
- Xis for the XDR client and should never be used by
- Xthe XDR stream implementations or the XDR primitives.
- X.LP
- XMacros for accessing operations
- X.LW x_getpostn() ,
- X.LW x_setpostn() ,
- Xand
- X.LW x_destroy()
- Xwere defined in Section 3.6.
- XThe operation
- X.LW x_inline()
- Xtakes two parameters:
- Xan XDR *, and an unsigned integer, which is a byte count.
- XThe routine returns a pointer to a piece of
- Xthe stream's internal buffer.
- XThe caller can then use the buffer segment for any purpose.
- XFrom the stream's point of view, the bytes in the
- Xbuffer segment have been consumed or put.
- XThe routine may return
- X.LW NULL
- Xif it cannot return a buffer segment of the requested size.
- X(The
- X.LW x_inline
- Xroutine is for cycle squeezers.
- XUse of the resulting buffer is not data-portable.
- XUsers are encouraged not to use this feature.)
- X.LP
- XThe operations
- X.LW x_getbytes()
- Xand
- X.LW x_putbytes()
- Xblindly get and put sequences of bytes
- Xfrom or to the underlying stream;
- Xthey return
- X.LW TRUE
- Xif they are successful, and
- X.LW FALSE
- Xotherwise. The routines have identical parameters (replace
- X.LW xxx ):
- X.LS
- Xbool_t
- Xxxxbytes(xdrs, buf, bytecount)
- X XDR *xdrs;
- X char *buf;
- X u_int bytecount;
- X.Lf
- XThe operations
- X.LW x_getlong()
- Xand
- X.LW x_putlong()
- Xreceive and put
- Xlong numbers from and to the data stream.
- XIt is the responsibility of these routines
- Xto translate the numbers between the machine representation
- Xand the (standard) external representation.
- XThe
- X.UX
- Xprimitives
- X.LW htonl()
- Xand
- X.LW ntohl()
- Xcan be helpful in accomplishing this.
- XSection 6 defines the standard representation of numbers.
- XThe higher-level XDR implementation assumes that
- Xsigned and unsigned long integers contain the same number of bits,
- Xand that nonnegative integers
- Xhave the same bit representations as unsigned integers.
- XThe routines return
- X.I TRUE
- Xif they succeed, and
- X.LW FALSE
- Xotherwise. They have identical parameters:
- X.LS
- Xbool_t
- Xxxxlong(xdrs, lp)
- X XDR *xdrs;
- X long *lp;
- X.Lf
- XImplementors of new XDR streams must make an XDR structure
- X(with new operation routines) available to clients,
- Xusing some kind of create routine.
- X.bp
- X.NH
- XXDR Standard
- X.LP
- XThis section defines the external data representation standard.
- XThe standard is independent of languages,
- Xoperating systems and hardware architectures.
- XOnce data is shared among machines, it should not matter that the data
- Xwas produced on a Sun, but is consumed by a VAX (or vice versa).
- XSimilarly the choice of operating systems should have no influence
- Xon how the data is represented externally.
- XFor programming languages,
- Xdata produced by a C program should be readable
- Xby a Fortran or Pascal program.
- X.LP
- XThe external data representation standard depends on the assumption that
- Xbytes (or octets) are portable.
- XA byte is defined to be eight bits of data.
- XIt is assumed that hardware
- Xthat encodes bytes onto various media
- Xwill preserve the bytes' meanings
- Xacross hardware boundaries.
- XFor example, the Ethernet standard suggests that bytes be
- Xencoded ``little endian'' style.
- XBoth Sun and VAX hardware implementations
- Xadhere to the standard.
- X.LP
- XThe XDR standard also suggests a language used to describe data.
- XThe language is a bastardized C;
- Xit is a data description language, not a programming language.
- X(The Xerox Courier Standard uses bastardized Mesa
- Xas its data description language.)
- X.NH 2
- XBasic Block Size
- X.LP
- XThe representation of all items requires
- Xa multiple of four bytes (or 32 bits) of data.
- XThe bytes are numbered
- X$0$ through $n-1$, where $(n ~ \fRmod\fP ~ 4) = 0$.
- XThe bytes are read or written to some byte stream
- Xsuch that byte $m$ always precedes byte $m+1$.
- X.NH 2
- XInteger
- X.LP
- XAn XDR signed integer is a 32-bit datum
- Xthat encodes an integer in the range
- X.LW [-2147483648,2147483647] .
- XThe integer is represented in two's complement notation.
- XThe most and least significant bytes are 0 and 3, respectively.
- XThe data description of integers is
- X.LW integer .
- X.NH 2
- XUnsigned Integer
- X.LP
- XAn XDR unsigned integer is a 32-bit datum
- Xthat encodes a nonnegative integer in the range
- X.LW [0,4294967295] .
- XIt is represented by an unsigned binary number whose most
- Xand least significant bytes are 0 and 3, respectively.
- XThe data description of unsigned integers is
- X.LW unsigned .
- X.NH 2
- XEnumerations
- X.LP
- XEnumerations have the same representation as integers.
- XEnumerations are handy for describing subsets of the integers.
- XThe data description of enumerated data is as follows:
- X.LS
- Xtypedef enum { name = value, .... } type-name;
- X.Lf
- XFor example the three colors red, yellow and blue
- Xcould be described by an enumerated type:
- X.LS
- Xtypedef enum { RED = 2, YELLOW = 3, BLUE = 5 } colors;
- X.Lf
- X.NH 2
- XBooleans
- X.LP
- XBooleans are important enough and occur frequently enough
- Xto warrant their own explicit type in the standard.
- XBoolean is an enumeration with the
- Xfollowing form:
- X.LS
- Xtypedef enum { FALSE = 0, TRUE = 1 } boolean;
- X.Lf
- X.NH 2
- XHyper Integer and Hyper Unsigned
- X.LP
- XThe standard also defines 64-bit (8-byte) numbers called
- X.LW "hyper integer"
- Xand
- X.LW "hyper unsigned" .
- XTheir representations are the obvious extensions of
- Xthe integer and unsigned defined above.
- XThe most and least significant bytes are 0 and 7, respectively.
- X.NH 2
- XFloating Point and Double Precision
- X.LP
- XThe standard defines the encoding for the floating point data types
- X.LW float
- X(32 bits or 4 bytes) and
- X.LW double
- X(64 bits or 8 bytes).
- XThe encoding used is the IEEE standard for normalized
- Xsingle- and double-precision floating point numbers.
- XSee the IEEE floating point standard for more information.
- XThe standard encodes the following three fields,
- Xwhich describe the floating point number:
- X.IP \fIS\fP
- XThe sign of the number.
- XValues 0 and 1 represent
- Xpositive and negative, respectively.
- X.IP \fIE\fP
- XThe exponent of the number, base 2.
- XFloats devote 8 bits to this field,
- Xwhile doubles devote 11 bits.
- XThe exponents for float and double are
- Xbiased by 127 and 1023, respectively.
- X.IP \fIF\fP
- XThe fractional part of the number's mantissa, base 2.
- XFloats devote 23 bits to this field,
- Xwhile doubles devote 52 bits.
- X.LP
- XTherefore, the floating point number is described by:
- X.EQ
- X(-1) sup S * 2 sup { E - Bias } * 1.F
- X.EN
- X.LP
- XJust as the most and least significant bytes of a number are 0 and 3,
- Xthe most and least significant bits of
- Xa single-precision floating point number are 0 and 31.
- XThe beginning bit (and most significant bit) offsets
- Xof $S$, $E$, and $F$ are 0, 1, and 9, respectively.
- X.LP
- XDoubles have the analogous extensions.
- XThe beginning bit (and
- Xmost significant bit) offsets of $S$, $E$, and $F$
- Xare 0, 1, and 12, respectively.
- X.LP
- XThe IEEE specification should be consulted concerning the encoding for
- Xsigned zero, signed infinity (overflow), and denormalized numbers (underflow).
- XUnder IEEE specifications, the ``NaN'' (not a number)
- Xis system dependent and should not be used.
- X.NH 2
- XOpaque Data
- X.LP
- XAt times fixed-sized uninterpreted data
- Xneeds to be passed among machines.
- XThis data is called
- X.LW opaque
- Xand is described as:
- X.LS
- Xtypedef opaque type-name[n];
- Xopaque name[n];
- X.Lf
- Xwhere
- X.LW n
- Xis the (static) number of bytes necessary to contain the opaque data.
- XIf
- X.LW n
- Xis not a multiple of four, then the
- X.LW n
- Xbytes are followed by enough (up to 3) zero-valued bytes
- Xto make the total byte count of the opaque object a multiple of four.
- X.NH 2
- XCounted Byte Strings
- X.LP
- XThe standard defines a string of $n$ (numbered $0$ through $n-1$)
- Xbytes to be the number $n$ encoded as
- X.LW unsigned ,
- Xand followed by the $n$ bytes of the string.
- XIf $n$ is not a multiple of four,
- Xthen the $n$ bytes are followed by
- Xenough (up to 3) zero-valued bytes
- Xto make the total byte count a multiple of four.
- XThe data description of strings is as follows:
- X.LS
- Xtypedef string type-name<N>;
- Xtypedef string type-name<>;
- Xstring name<N>;
- Xstring name<>;
- X.Lf
- XNote that the data description language uses angle brackets (< and >)
- Xto denote anything that is varying-length
- X(as opposed to square brackets to denote fixed-length sequences of data).
- X.LP
- XThe constant
- X.LW N
- Xdenotes an upper bound of the number of bytes that a
- Xstring may contain.
- XIf
- X.LW N
- Xis not specified, it is assumed to be $2 sup 32 - 1$,
- Xthe maximum length.
- XThe constant
- X.LW N
- Xwould normally be found in a protocol specification.
- XFor example, a filing protocol may state
- Xthat a file name can be no longer than 255 bytes, such as:
- X.LS
- Xstring filename<255>;
- X.Lf
- X.LP
- XThe XDR specification does not say what the
- Xindividual bytes of a string represent;
- Xthis important information is left to higher-level specifications.
- XA reasonable default is to assume
- Xthat the bytes encode ASCII characters.
- X.NH 2
- XFixed Arrays
- X.LP
- XThe data description for fixed-size arrays of
- Xhomogeneous elements is as follows:
- X.LS
- Xtypedef elementtype type-name[n];
- Xelementtype name[n];
- X.Lf
- XFixed-size arrays of elements numbered $0$ through $n-1$
- Xare encoded by individually encoding the elements of the array
- Xin their natural order, $0$ through $n-1$.
- X.NH 2
- XCounted Arrays
- X.LP
- XCounted arrays provide the ability to encode varyiable-length arrays
- Xof homogeneous elements.
- XThe array is encoded as:
- Xthe element count $n$ (an unsigned integer),
- Xfollowed by the encoding of each of the array's elements,
- Xstarting with element $0$ and progressing through element $n-1$.
- XThe data description for counted arrays
- Xis similar to that of counted strings:
- X.LS
- Xtypedef elementtype type-name<N>;
- Xtypedef elementtype type-name<>;
- Xelementtype name<N>;
- Xelementtype name<>;
- X.Lf
- XAgain, the constant
- X.LW N
- Xspecifies the maximum acceptable
- Xelement count of an array; if
- X.LW N
- Xis not specified, it is assumed to be $2 sup 32 - 1$.
- X.NH 2
- XStructures
- X.LP
- XThe data description for structures is very similar to
- Xthat of standard C:
- X.LS
- Xtypedef struct {
- X component-type component-name;
- X ...
- X} type-name;
- X.Lf
- XThe components of the structure are encoded
- Xin the order of their declaration in the structure.
- X.NH 2
- XDiscriminated Unions
- X.LP
- XA discriminated union is a type composed of a discriminant followed by a type
- Xselected from a set of prearranged types according to the value of the
- Xdiscriminant.
- XThe type of the discriminant is always an enumeration.
- XThe component types are called ``arms'' of the union.
- XThe discriminated union is encoded as its discriminant followed by
- Xthe encoding of the implied arm.
- XThe data description for discriminated unions is as follows:
- X.LS
- Xtypedef union switch (discriminant-type) {
- X discriminant-value: arm-type;
- X ...
- X default: default-arm-type;
- X} type-name;
- X.Lf
- XThe default arm is optional.
- XIf it is not specified, then a valid
- Xencoding of the union cannot take on unspecified discriminant values.
- XMost specifications neither need nor use default arms.
- X.NH 2
- XMissing Specifications
- X.LP
- XThe standard lacks representations for bit fields and bitmaps,
- Xsince the standard is based on bytes.
- XThis is not to say that no specification should be attempted.
- X.NH 2
- XLibrary Primitive / XDR Standard Cross Reference
- X.LP
- XThe following table describes the association between
- Xthe C library primitives discussed in Section 3,
- Xand the standard data types defined in this section:
- X.LP
- X.TS
- Xbox;
- XcfBI s s
- XcfI cfI cfI
- XrfL | cfL | l.
- X.sp.1
- XPrimitives and Data Types
- X.sp.1
- X_
- XC Primitive XDR Type Sections
- X_
- Xxdr_int
- Xxdr_long integer 3.1, 6.2
- Xxdr_short
- X_
- Xxdr_u_int
- Xxdr_u_long unsigned 3.1, 6.3
- Xxdr_u_short
- X_
- X- hyper integer 6.6
- X hyper unsigned
- X_
- Xxdr_float float 3.2, 6.7
- X_
- Xxdr_double double 3.2, 6.7
- X_
- Xxdr_enum enum_t 3.3, 6.4
- X_
- Xxdr_bool bool_t 3.3, 6.5
- X_
- Xxdr_string string 3.5.1, 6.9
- Xxdr_bytes 3.5.2
- X_
- Xxdr_array \fR(varying arrays)\fP 3.5.3, 6.11
- X_
- X- \fR(fixed arrays)\fP 3.5.5, 6.10
- X_
- Xxdr_opaque opaque 3.5.4, 6.8
- X_
- Xxdr_union union 3.5.6, 6.13
- X_
- Xxdr_reference - 3.5.7
- X_
- X- struct 6.6
- X.TE
- X.TN "Primitives and Data Types"
- X.bp
- X.NH
- XAdvanced Topics
- X.LP
- XThis section describes techniques for passing data structures
- Xthat are not covered in the preceding sections.
- XSuch structures include linked lists (of arbitrary lengths).
- XUnlike the simpler examples covered in the earlier sections,
- Xthe following examples are written using both
- Xthe XDR C library routines and the XDR data description language.
- XSection 6 describes the XDR data definition language used below.
- X.NH 2
- XLinked Lists
- X.LP
- XThe last example in Section 2 presented a C data structure and its
- Xassociated XDR routines for a person's gross assets and liabilities.
- XThe example is duplicated below:
- X.LS
- Xstruct gnumbers {
- X long g_assets;
- X long g_liabilities;
- X};
- X.sp.5
- Xbool_t
- Xxdr_gnumbers(xdrs, gp)
- X XDR *xdrs;
- X struct gnumbers *gp;
- X{
- X if (xdr_long(xdrs, &(gp->g_assets)))
- X return(xdr_long(xdrs, &(gp->g_liabilities)));
- X return(FALSE);
- X}
- X.Lf
- XNow assume that we wish to implement a linked list of such information.
- XA data structure could be constructed as follows:
- X.LS
- Xtypedef struct gnnode {
- X struct gnumbers gn_numbers;
- X struct gnnode *nxt;
- X};
- X.sp.5
- Xtypedef struct gnnode *gnumbers_list;
- X.Lf
- XThe head of the linked list can be thought of as the data object;
- Xthat is, the head is not merely a convenient shorthand for a structure.
- XSimilarly the
- X.LW nxt
- Xfield is used to indicate whether or not the object has terminated.
- XUnfortunately, if the object continues, the
- X.LW nxt
- Xfield is also the address
- Xof where it continues.
- XThe link addresses carry no useful information when
- Xthe object is serialized.
- X.LP
- XThe XDR data description of this linked list is described by the
- Xrecursive type declaration of gnumbers_list:
- X.LS
- Xstruct gnumbers {
- X unsigned g_assets;
- X unsigned g_liabilities;
- X};
- X.Lf
- X.LS
- Xtypedef union switch (boolean) {
- X case TRUE: struct {
- X struct gnumbers current_element;
- X gnumbers_list rest_of_list;
- X };
- X case FALSE: struct {};
- X} gnumbers_list;
- X.Lf
- XIn this description,
- Xthe boolean indicates whether there is more data following it.
- XIf the boolean is
- X.LW FALSE ,
- Xthen it is the last data field of the structure.
- XIf it is
- X.LW TRUE ,
- Xthen it is followed by a
- X.LW gnumbers
- Xstructure and (recursively) by a
- X.LW gnumbers_list
- X(the rest of the object).
- XNote that the C declaration has no boolean explicitly declared in it
- X(though the
- X.LW nxt
- Xfield implicitly carries the information), while
- Xthe XDR data description has no pointer explicitly declared in it.
- X.LP
- XHints for writing a set of XDR routines to successfully (de)serialize
- Xa linked list of entries can be taken
- Xfrom the XDR description of the pointer-less data.
- XThe set consists of the mutually recursive routines
- X.LW xdr_gnumbers_list ,
- X.LW xdr_wrap_list ,
- Xand
- X.LW xdr_gnnode .
- X.LS
- Xbool_t
- Xxdr_gnnode(xdrs, gp)
- X XDR *xdrs;
- X struct gnnode *gp;
- X{
- X return(xdr_gnumbers(xdrs, &(gp->gn_numbers)) &&
- X xdr_gnumbers_list(xdrs, &(gp->nxt)) );
- X}
- X.Lf
- SHAR_EOF
- if test 49809 -ne "`wc -c < 'rpc/doc/xdr.spec.p1'`"
- then
- echo shar: "error transmitting 'rpc/doc/xdr.spec.p1'" '(should have been 49809 characters)'
- fi
- chmod 444 'rpc/doc/xdr.spec.p1'
- fi
- exit 0
- # End of shell archive
-